package com.example.rabbit.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 发布确认 - 高级
 * <p>
 * 两种情况
 * 1. 生产者发送消息，如果此时交换器出现异常，收不到消息，那么应该将消息缓存，生产者需要交换机确认收到了消息。【此时使用回调确认消息】
 * 2. 当交换机完好，队列出现了问题，那么【使用备份交换机中的队列来接收消息并处理】
 * ** 当同时设置并开启了 交换机回调确认 和 备份交换机，那么 [备份交换机优先级更高]。
 * ** 可以通过 controller 发送一条消息来确认，消息会直接进入备份交换机
 *
 * @Author ifredomvip@gmail.com
 **/
@Configuration
public class SeniorConfirmConfig {
    public static final String CONFIRM_EXCHANGE = "senior_confirm_exchange";
    public static final String CONFIRM_QUEUE = "senior_confirm_queue";
    public static final String CONFIRM_ROUTING_KEY = "senior_confirm_routingKey";


    // 备份

    public static final String BACKUP_EXCHANGE = "senior_backup_exchange";
    public static final String BACKUP_QUEUE = "senior_backup_queue";
    public static final String BACKUP_WARNING_QUEUE = "senior_warning_queue";

    /**
     * 因为要传参，所以使用构造方式创建 DirectExchange 类
     * 将确认交换机指向备份交换机，并设置备份交换机持久化
     *
     * @return {@link DirectExchange}
     */
    @Bean(CONFIRM_EXCHANGE)
    public DirectExchange getConfirmExchange() {
//        return ExchangeBuilder.directExchange(CONFIRM_EXCHANGE).build();

//       设置备份交换机写法。写法一。

//        return ExchangeBuilder.directExchange(CONFIRM_EXCHANGE).withArgument("alternate-exchange", BACKUP_EXCHANGE).build();

//       设置备份交换机写法。写法二。

        return ExchangeBuilder.directExchange(CONFIRM_EXCHANGE).alternate(BACKUP_EXCHANGE).build();
    }

    @Bean
    public Queue getConfirmQueue() {
        return new Queue(CONFIRM_QUEUE);
    }

    @Bean
    public Binding doBindingConfirm(@Qualifier("getConfirmQueue") Queue queue, @Qualifier(CONFIRM_EXCHANGE) DirectExchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange).with(CONFIRM_ROUTING_KEY);
    }


    /**
     * 备份交换机
     * 扇出交换机
     *
     * @return {@link DirectExchange}
     */
    @Bean
    public FanoutExchange getBackupExchange() {
        return new FanoutExchange(BACKUP_EXCHANGE);
    }

    /**
     * 备份队列
     *
     * @return {@link Queue}
     */
    @Bean(BACKUP_QUEUE)
    public Queue getBackupQueue() {
        return new Queue(BACKUP_QUEUE);
    }

    /**
     * 警告队列
     *
     * @return {@link Queue}
     */
    @Bean(BACKUP_WARNING_QUEUE)
    public Queue getBackupWarningQueue() {
        return new Queue(BACKUP_WARNING_QUEUE);
    }

    /**
     * 执行绑定 ： 备份队列 绑定到 确认交换机
     * 扇出交换机不需要routingKey
     *
     * @param queue          队列
     * @param directExchange 直接交换
     * @return {@link Binding}
     */
    @Bean
    public Binding doBindingBackup(@Qualifier(BACKUP_QUEUE) Queue queue, @Qualifier("getBackupExchange") FanoutExchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange);
    }

    /**
     * 执行绑定 ： 警告队列 绑定到 确认交换机
     * 扇出交换机不需要routingKey
     *
     * @param queue          队列
     * @param directExchange 直接交换
     * @return {@link Binding}
     */
    @Bean
    public Binding doBindingBackupWarning(@Qualifier(BACKUP_WARNING_QUEUE) Queue queue, @Qualifier("getBackupExchange") FanoutExchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange);
    }


}
